<script>
import {
  Check,
  CirclePlus,
  Close,
  Delete,
  EditPen,
  Finished,
  Football,
  More,
  MoreFilled,
  Plus,
  PriceTag,
  SetUp,
} from "@element-plus/icons-vue";
import request from "../../../../utils/Request.js";
import { ElMessage, ElMessageBox } from "element-plus";
import store from "../../../../store/index.js";
import { MdEditor } from "md-editor-v3";
import "md-editor-v3/lib/style.css";

export default {
  name: "ApiDoc",
  components: {
    CirclePlus,
    Delete,
    EditPen,
    Football,
    Check,
    Plus,
    Close,
    MoreFilled,
    More,
    MdEditor,
  },
  computed: {
    store() {
      return store;
    },
    MoreFilled() {
      return MoreFilled;
    },
    Delete() {
      return Delete;
    },
    EditPen() {
      return EditPen;
    },
    Close() {
      return Close;
    },
    Finished() {
      return Finished;
    },
    SetUp() {
      return SetUp;
    },
    Plus() {
      return Plus;
    },
    PriceTag() {
      return PriceTag;
    },
    contentsLength() {
      if (this.apiData.contents == null) return 0;
      return this.apiData.contents.length;
    },
  },
  props: {
    id: String,
    index: Number,
  },
  watch: {
    tagPopoverVisible(nV, oV) {
      if (nV === false) {
        this.tagData = {
          name: "",
          color: "",
        };
        this.pickColor = "";
      }
    },
    contentsLength(nV, oV) {
      for (let i = 0; i < nV - oV; i++) this.moreVisibleList.push(false);
    },
    "apiData.url"(nV, oV) {
      this.changeTabName();
    },
    "apiData.method"(nV, oV) {
      this.changeTabName();
    },
    "apiData.description"(nV, oV) {
      this.changeTabName();
    },
  },
  data() {
    return {
      tagData: {
        name: "",
        color: "#61BD4FFF",
      },
      tagRules: {
        name: [
          { required: true, message: "请输入标签名字", trigger: "blur" },
          {
            min: 1,
            max: 20,
            message: "标签名字长度应该不大于20",
            trigger: "blur",
          },
        ],
        color: [{ required: true, message: "请选择一个颜色", trigger: "blur" }],
      },
      tags: [
        {
          id: 1,
          name: "tag1",
          color: "#123456",
        },
        {
          id: 1,
          name: "tag2",
          color: "blue",
        },
        {
          id: 1,
          name: "tag3",
          color: "red",
        },
      ],
      apiData: {
        url: "",
        method: "POST",
        contents: [
          {
            id: 1,
            label: "参数",
            type: 0,
            order: 1,
            params: [
              {
                // id: 1,
                name: "can",
                type: "String",
                need: true,
              },
            ],
          },
          {
            id: 2,
            label: "描述",
            type: 1,
            content: "content",
            order: 2,
          },
        ],
        description: "",
      },
      apiRules: {
        methodAndUrl: [
          {
            validator: (rule, value, callback) => {
              const pattern = new RegExp(
                "^(https?:\\/\\/)?" + // protocol
                  "((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" + // domain name and extension
                  "((\\d{1,3}\\.){3}\\d{1,3}))" + // OR ip (v4) address
                  "(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // port and path
                  "(\\?[;&a-z\\d%_.~+=-]*)?" + // query string
                  "(\\#[-a-z\\d_]*)?$",
                "i"
              ); // fragment locator
              if (this.methodList.indexOf(this.apiData.method) === -1) {
                callback(new Error("请选择正确的请求方式"));
              } else if (
                this.apiData.url !== "" &&
                this.apiData.url != null &&
                !pattern.test(this.apiData.url)
              ) {
                callback(new Error("请填写正确的请求地址"));
              } else {
                callback();
              }
            },
            trigger: "blur",
          },
        ],
        description: [
          { required: false, message: "", trigger: "blur" },
          {
            min: 1,
            max: 255,
            message: "描述长度应该不大于255",
            trigger: "blur",
          },
        ],
      },
      methodList: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
      tagColorList: [
        "#61BD4FFF",
        "#F2D600FF",
        "#FF9F1AFF",
        "#EB5A46FF",
        "#C377E0FF",
        "#0079BFFF",
        "#00C2E0FF",
        "#51E898FF",
        "#FF78CBFF",
      ],
      pickColor: "",
      tagPopoverVisible: false,
      moreVisibleList: [],
      renameBlockDialogVisible: false,
      renameBlockData: {
        name: "",
      },
      renameBlockRules: {
        name: [
          { required: true, message: "请输入名称", trigger: "blur" },
          { min: 1, max: 20, message: "名称长度应该不大于20", trigger: "blur" },
        ],
      },
      contentOrderVisible: false,
    };
  },
  methods: {
    changeTabName() {
      if (!store.state.planeTabIsModified[this.index])
        store.state.planeTabIsModified[this.index] = true;
    },
    addTag() {
      let tagForm = this.$refs["tagFormRef"];

      tagForm.validate((isValid, invalidFields) => {
        if (isValid) {
          request({
            url: "/api/project/api/tag",
            method: "post",
            data: {
              projectId: this.$route.params.projectId,
              apiId: this.id,
              name: this.tagData.name,
              color: this.tagData.color,
            },
          }).then(({ data }) => {
            if (data.code === 0) {
              ElMessage.success("添加标签成功");
              this.tags.push({
                id: data.data,
                name: this.tagData.name,
                color: this.tagData.color,
              });
              this.tagPopoverVisible = false;
            } else {
              ElMessage.error(data.msg);
            }
          });
        }
      });
    },
    closeTag(id, index) {
      request({
        url: "/api/project/api/tag/remove",
        method: "post",
        data: {
          projectId: this.$route.params.projectId,
          id: id,
        },
      }).then(({ data }) => {
        if (data.code === 0) {
          this.tags.splice(index, 1);
        } else {
          ElMessage.error(data.msg);
        }
      });
    },

    renameBlock(item) {
      ElMessageBox.prompt("修改名称", "重命名", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        "input-value": item.label,
        "input-validator": (value) => {
          if (value === "") return "名称不能为空";
          else if (value === item.label) return "请修改名称";
          return true;
        },
      }).then(({ value }) => {
        request({
          url: "/api/project/api/content/rename",
          method: "post",
          data: {
            id: item.id, // content Id
            projectId: this.$route.params.projectId,
            apiId: this.id,
            label: value,
          },
        }).then(({ data }) => {
          if (data.code === 0) {
            item.label = value;
            ElMessage.success("修改名称成功");
          } else {
            ElMessage.error("修改失败，请重试！");
          }
        });
      });
    },

    removeBlock(id, index) {
      ElMessageBox.confirm("是否要删除该块？", "提醒", {
        confirmButtonText: "删除",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        request({
          url: "/api/project/api/content/remove",
          method: "post",
          data: {
            id: id, // content Id
            projectId: this.$route.params.projectId,
            apiId: this.id,
          },
        }).then(({ data }) => {
          if (data.code === 0) {
            this.apiData.contents.splice(index, 1);
          } else {
            ElMessage.error("移除失败，请重试！");
          }
        });
      });
    },
    addBlock(type) {
      ElMessageBox.prompt("块的名称", "新建块", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        "input-validator": (value) => {
          if (value === "") return "名称不能为空";
          else if (value.length > 20) return "名称长度应该不大于20";
          return true;
        },
      }).then(({ value }) => {
        let typeInt = type === "param" ? 0 : 1;
        let newOrder =
          this.apiData.contents[this.apiData.contents.length - 1].order + 10;
        request({
          url: "/api/project/api/content/add",
          method: "post",
          data: {
            apiId: this.id,
            projectId: this.$route.params.projectId,
            label: value,
            type: typeInt,
            order: newOrder,
          },
        }).then(({ data }) => {
          if (data.code === 0) {
            let newBlock = {
              id: data.data,
              label: value,
              type: typeInt,
              order: newOrder,
            };
            if (type === 0) {
              newBlock.params = [];
            } else {
              newBlock.content = "";
            }
            this.apiData.contents.push(newBlock);
            ElMessage.success("添加成功");
          } else {
            ElMessage.error(data.msg);
          }
        });
      });
    },
    saveApi() {
      let form = this.$refs["formRef"];

      form.validate((isValid) => {
        if (isValid) {
          this.apiData.apiId = this.id;
          this.apiData.projectId = this.$route.params.projectId;
          request({
            url: "/api/project/api/save",
            method: "post",
            data: this.apiData,
          }).then(({ data }) => {
            if (data.code === 0) {
              ElMessage.success("保存成功");
              store.state.planeTabIsModified[this.index] = false;
            } else {
              ElMessage.error("保存文档出现错误");
            }
          });
        }
      });
    },
    getTagList() {
      request({
        url: "/api/project/api/tag/list",
        method: "post",
        data: {
          id: this.id,
          projectId: this.$route.params.projectId,
        },
      }).then(({ data }) => {
        if (data.code === 0) {
          this.tags = data.data;
        } else {
          ElMessage.error("获取文档标签异常");
        }
      });
    },

    getApiData() {
      this.apiData = {};
      request({
        url: "/api/project/api/data",
        method: "post",
        data: {
          id: this.id,
          projectId: this.$route.params.projectId,
        },
      }).then(({ data }) => {
        if (data.code === 0) {
          this.apiData = data.data;
          if (this.apiData.contents == null) this.apiData.contents = [];
          for (let i = 0; i < this.apiData.contents.length; i++) {
            if (this.apiData.contents[i].type === 0) {
              this.apiData.contents[i].params = JSON.parse(
                this.apiData.contents[i].params
              );
            } else if (this.apiData.contents[i].type === 1) {
              if (this.apiData.contents[i].content == null) {
                this.apiData.contents[i].content = "";
              }
            }
          }
        } else {
          ElMessage.error("获取文档数据异常");
        }
      });
    },

    contentOrderNodeDrop(draggingNode, dropNode, type) {
      if (!store.state.planeTabIsModified[this.index])
        store.state.planeTabIsModified[this.index] = true;
      for (let i = 0; i < this.apiData.contents.length; i++) {
        this.apiData.contents[i].order = i * 10;
      }
    },

    $imgAdd(files, callback) {
      if (files == null || files.length === 0) return;
      let file = files[0];
      // 图片文件格式验证
      if (file.type.indexOf("image") === -1) {
        ElMessage.error("请上传图片");
        return;
      }
      // 大小 <= 2M
      if (file.size > 2 * 1024 * 1024) {
        ElMessage.error("图片大小不能超过2M");
        return;
      }

      let formdata = new FormData();
      formdata.append("image", file);
      request({
        url: "/api/project/doc/upload/image",
        method: "post",
        data: formdata,
        headers: {
          "Content-Type": "multipart/form-data",
        },
      }).then(({ data }) => {
        // console.log(data)
        if (data.code === 0) {
          callback([{ url: data.data.url, alt: file.name, title: file.name }]);
        } else {
          console.log(data);
          ElMessage.error(data.msg);
        }
      });
    },

    ctrlSave(event) {
      if (event.ctrlKey && event.key === "s") {
        event.preventDefault();
        this.saveApi();
      }
    },
  },
  created() {
    this.getTagList();
    this.getApiData();
  },
};
</script>

<template>
  <div v-on:keydown="ctrlSave">
    <el-row v-show="tags.length !== 0" style="margin-bottom: 20px">
      <el-tag
        v-for="(tag, index) in tags"
        style="margin-right: 5px; box-shadow: 0 0 0 0; border: none"
        :key="tag.id"
        closable
        :color="tag.color"
        @close="closeTag(tag.id, index)"
        effect="dark"
        size="small"
      >
        {{ tag.name }}
      </el-tag>
    </el-row>

    <el-form ref="formRef" :model="apiData" :rules="apiRules">
      <el-form-item prop="methodAndUrl">
        <el-row justify="center" style="width: 100%">
          <el-col :span="2">
            <el-select v-model="apiData.method" style="width: 100%">
              <el-option
                v-for="method in methodList"
                :value="method"
                :key="method"
              >
                {{ method }}
              </el-option>
            </el-select>
          </el-col>

          <el-col :span="20">
            <el-input
              style="width: 100%"
              v-model="apiData.url"
              placeholder="请求地址"
            />
          </el-col>

          <!--      添加标签-->
          <el-col :span="2">
            <el-popover
              placement="bottom-start"
              :width="320"
              :visible="tagPopoverVisible"
            >
              <template #reference>
                <el-button
                  :icon="PriceTag"
                  type="success"
                  style="width: 90%; margin-left: 10%"
                  @click="tagPopoverVisible = !tagPopoverVisible"
                >
                  添加标签
                </el-button>
              </template>
              <template #default>
                <el-row>
                  <el-col :offset="22" :span="2">
                    <el-link
                      @click="tagPopoverVisible = false"
                      :underline="false"
                    >
                      <template #icon>
                        <el-icon size="large">
                          <Close />
                        </el-icon>
                      </template>
                    </el-link>
                  </el-col>
                </el-row>

                <el-form
                  ref="tagFormRef"
                  :model="tagData"
                  :rules="tagRules"
                  label-position="top"
                >
                  <el-form-item prop="name" label="名称">
                    <el-input
                      v-model="tagData.name"
                      placeholder="请输入标签的名称"
                    />
                  </el-form-item>

                  <el-form-item prop="color" label="请选择一个标签的颜色">
                    <el-row :gutter="10">
                      <el-col
                        :span="4.8"
                        v-for="color in tagColorList"
                        style="margin-bottom: 10px"
                        :key="color"
                      >
                        <el-button
                          :color="color"
                          dark
                          style="width: 100%"
                          @click="tagData.color = color"
                        >
                          <template #icon>
                            <span v-show="tagData.color === color">
                              <el-icon size="large" :color="'#FFFFFFFF'">
                                <Check />
                              </el-icon>
                            </span>
                          </template>
                        </el-button>
                      </el-col>
                      <el-col :span="4.8" style="margin-bottom: 10px">
                        <el-color-picker
                          v-model="pickColor"
                          :predefine="tagColorList"
                          @change="(value) => (tagData.color = value)"
                        />
                      </el-col>
                    </el-row>
                  </el-form-item>

                  <el-form-item>
                    <el-button
                      plain
                      style="width: 100%"
                      type="info"
                      @click="addTag"
                      >添加</el-button
                    >
                  </el-form-item>
                </el-form>
              </template>
            </el-popover>
          </el-col>
          <!--      添加标签结束-->
        </el-row>
      </el-form-item>

      <el-form-item prop="description">
        <el-row style="width: 100%">
          <el-col :span="22">
            <el-input
              style="width: 100%"
              v-model="apiData.description"
              placeholder="请输入简单的描述"
            />
          </el-col>

          <el-col :span="2">
            <el-button
              style="width: 90%; margin-left: 10%"
              plain
              :icon="Finished"
              @click="saveApi"
            >
              保存文档
            </el-button>
          </el-col>
        </el-row>
      </el-form-item>

      <el-row style="margin-top: 20px">
        <el-col :span="2">
          <el-link
            type="primary"
            :underline="false"
            :icon="Plus"
            @click="addBlock('param')"
          >
            添加参数块
          </el-link>
        </el-col>

        <el-col :span="2">
          <el-link
            type="primary"
            :underline="false"
            :icon="Plus"
            @click="addBlock('desc')"
          >
            添加描述块
          </el-link>
        </el-col>
        <el-col :span="2">
          <el-popover
            placement="right"
            :width="400"
            :visible="contentOrderVisible"
          >
            <template #reference>
              <el-link
                type="primary"
                :underline="false"
                :icon="SetUp"
                @click="contentOrderVisible = !contentOrderVisible"
              >
                排列顺序
              </el-link>
            </template>
            <el-row style="margin-bottom: 5px">
              <el-col :span="22">
                <el-text type="info" size="large">拖动以调整顺序</el-text>
              </el-col>
              <el-col :span="2">
                <el-link
                  @click="contentOrderVisible = false"
                  :underline="false"
                >
                  <template #icon>
                    <el-icon size="large">
                      <Close />
                    </el-icon>
                  </template>
                </el-link>
              </el-col>
            </el-row>

            <el-row>
              <el-col :span="24">
                <el-tree
                  :data="apiData.contents"
                  :props="{ label: 'label' }"
                  draggable
                  :allow-drop="
                    (draggingNode, dropNode, type) => {
                      return type !== 'inner';
                    }
                  "
                  @node-drop="contentOrderNodeDrop"
                />
              </el-col>
            </el-row>
            <el-row>
              <el-col :span="4" :offset="20">
                <el-button @click="saveApi" type="primary"> 保存 </el-button>
              </el-col>
            </el-row>
          </el-popover>
        </el-col>
      </el-row>

      <el-row>
        <el-collapse style="width: 100%">
          <el-collapse-item
            v-for="(item, index) in apiData.contents"
            style="width: 100%; margin-top: 20px"
            :name="item.id"
            @mouseover="moreVisibleList[index] = true"
            @mouseout="moreVisibleList[index] = false"
            :key="item.id"
          >
            <template #title>
              <el-text type="info" size="large">
                <el-icon>
                  <Football />
                </el-icon>
                <b>{{ item.label }}</b>
              </el-text>

              <el-text v-show="moreVisibleList[index]">
                <span>&nbsp;&nbsp;&nbsp;</span>
                <el-tooltip effect="dark" content="修改名称" placement="top">
                  <el-link
                    :icon="EditPen"
                    :underline="false"
                    @click="renameBlock(item)"
                  />
                </el-tooltip>
                <span>&nbsp;&nbsp;</span>
                <el-tooltip effect="dark" content="删除" placement="top">
                  <el-link
                    :icon="Delete"
                    :underline="false"
                    @click="removeBlock(item.id, index)"
                  />
                </el-tooltip>
              </el-text>
            </template>

            <!--          参数块-->
            <span v-if="item.type === 0">
              <el-table :data="item.params" style="width: 100%">
                <template #empty>
                  <el-text type="info">
                    点击右上角<el-icon><CirclePlus /></el-icon>添加参数吧
                  </el-text>
                </template>

                <el-table-column prop="name" label="参数名" width="180">
                  <template #default="{ row, column, $index }">
                    <el-input v-model="row.name" />
                  </template>
                </el-table-column>

                <el-table-column prop="type" label="类型" width="180">
                  <template #default="{ row, column, $index }">
                    <el-input v-model="row.type" />
                  </template>
                </el-table-column>

                <el-table-column prop="description" label="描述">
                  <template #default="{ row, column, $index }">
                    <el-input v-model="row.description" />
                  </template>
                </el-table-column>

                <el-table-column
                  prop="must"
                  label="必需"
                  width="80"
                  align="center"
                >
                  <template #default="{ row, column, $index }">
                    <el-checkbox v-model="row.need" />
                  </template>
                </el-table-column>

                <!--              更多-->
                <el-table-column width="80" align="center">
                  <template #header="{ column, $index }">
                    <el-tooltip
                      effect="dark"
                      content="添加参数"
                      placement="top"
                    >
                      <el-link
                        :underline="false"
                        @click="
                          () => {
                            if (item.params == null) {
                              item.params = [];
                            }
                            item.params.push({
                              need: false,
                              name: '',
                              type: '',
                            });
                          }
                        "
                      >
                        <template #icon>
                          <el-icon size="large">
                            <CirclePlus />
                          </el-icon>
                        </template>
                      </el-link>
                    </el-tooltip>
                  </template>
                  <template #default="{ row, column, $index }">
                    <el-tooltip effect="dark" content="删除" placement="bottom">
                      <el-link
                        :underline="false"
                        @click="item.params.splice($index, 1)"
                      >
                        <template #icon>
                          <el-icon size="large">
                            <Close />
                          </el-icon>
                        </template>
                      </el-link>
                    </el-tooltip>
                  </template>
                </el-table-column>
              </el-table>
            </span>

            <!--          描述块-->
            <div style="border: 1px solid #ccc" v-else-if="item.type === 1">
              <!-- <mavon-editor
                ref="md"
                style="width: 100%; height: 300px;overflow-y: hidden; box-shadow: none"
                aria-placeholder="开始描述..."
                v-model="item.content"
                ishljs
                @change="changeTabName"
                @imgAdd="$imgAdd"
            /> -->
              <MdEditor
                :editorId="'md-e-apidoc' + item.id"
                style="
                  width: 100%;
                  height: 300px;
                  overflow-y: hidden;
                  box-shadow: none;
                "
                placeholder="开始描述..."
                v-model="item.content"
                @onChange="changeTabName"
                @onUploadImg="$imgAdd"
                @onSave="saveApi"
                :toolbarsExclude="['github']"
              />
            </div>
          </el-collapse-item>
        </el-collapse>
      </el-row>
    </el-form>

    <br />
  </div>
</template>

<style scoped>
:deep(.el-input__wrapper) {
  border-radius: 0 0 0 0;
  box-shadow: 0 0 0 0 var(--el-input-border-color, var(--el-border-color)) inset;
  border: none;
  border-bottom: 1px solid #e9e9eb;
}

:deep(.el-input__wrapper.is-focus) {
  box-shadow: 0 -1px 0 0 var(--el-input-focus-border-color) inset;
}

:deep(.el-select:hover:not(.el-select--disabled) .el-input__wrapper) {
  box-shadow: 0 -1px 0 0 var(--el-select-border-color-hover) inset;
}

:deep(.el-select .el-input.is-focus .el-input__wrapper) {
  box-shadow: 0 -1px 0 0 var(--el-select-input-focus-border-color) inset !important;
}

:deep(.el-select .el-input__wrapper.is-focus) {
  box-shadow: 0 -1px 0 0 var(--el-select-input-focus-border-color) inset !important;
}

:deep(.el-collapse-item__header) {
  border: none;
}

:deep(.el-collapse) {
  border: none;
}

:deep(.el-collapse-item__wrap) {
  border: none;
}

:deep(.el-color-picker__trigger) {
  height: 32px;
  width: 46px;
  padding: 0;
  margin-top: 2px;
}

:deep(.el-tree-node__content) {
  margin-bottom: 10px;
  border: 1px dashed var(--el-border-color);
}
</style>